(function() {

    var ns = {
        core : bump.$core.namespace('bump.framework.core'),
        ui : bump.$core.namespace('bump.framework.ui')
    };

    ns.ui.quickHint = {

        options : {
            xOffset : 20,
            yOffset : 15
        },

        /**
         * Hint dom element.
         */
        domElement : null,

        currentHoveredElement : null,

        currentHoveredElementTitle : null,

        getHintPosition : function(mouseX, mouseY) {
            var
            quickHintElement = $(this.domElement),
            quickHintWidth = quickHintElement.width(),
            quickHintHeight = quickHintElement.height(),
            windowElement = $(window),
            windowWidth = windowElement.width(),
            windowHeight = windowElement.height();

            if (mouseX + quickHintWidth + this.options.xOffset * 2 > windowWidth) {
                mouseX = mouseX - quickHintWidth - this.options.xOffset * 2;
            } else {
                mouseX += this.options.xOffset;
            }

            if (mouseY + quickHintHeight + this.options.yOffset > windowHeight) {
                mouseY = mouseY - quickHintHeight - this.options.yOffset;
            } else {
                mouseY += this.options.yOffset;
            }

            return { x : mouseX, y : mouseY };
        },
        
        show : function(e) {
            this.currentHoveredElement = e.target;

            this.currentHoveredElementTitle = this.currentHoveredElement.getAttribute('title');
            this.currentHoveredElement.setAttribute('title', '');

            var position = this.getHintPosition(e.pageX, e.pageY);

            this.domElement.style.left = position.x + 'px';
            this.domElement.style.top = position.y + 'px';
            this.domElement.innerHTML = this.currentHoveredElementTitle;
            this.domElement.style.display = 'block';
        },

        hide : function() {
            this.currentHoveredElement.setAttribute('title', this.currentHoveredElementTitle);
            this.domElement.style.display = 'none';
            this.currentHoveredElement = null;
        },

        /**
         * Creates hint dom element.
         */
        createDomElement : function() {
            this.domElement = document.createElement('div');
            this.domElement.setAttribute('id', 'quick-hint');

            document.body.appendChild(this.domElement);
        },

        bindMouseEventsHandlers : function() {
            var self = this;

            $(".quick-hint[title]").hover(
                ns.core.func.proxy(this.show, this),
                ns.core.func.proxy(this.hide, this)
            ).mousemove(
                function(e) {
                    var position = self.getHintPosition(e.pageX, e.pageY);
                    self.domElement.style.left = position.x + 'px';
                    self.domElement.style.top = position.y + 'px';
                }
            );
        },

        /**
         * Initialize instance using options.
         */
        initialize : function() {
            this.createDomElement();
            this.bindMouseEventsHandlers();
        }

    };

    $(document).ready(function() {
        ns.ui.quickHint.initialize();
    });

})();
